#ifndef __TOYM__NET__SOCKET_H__
#define __TOYM__NET__SOCKET_H__

#include "Base/noncopyable.h"
#include "Base/Timestamp.h"
#include "InetAddress.h"

namespace toym
{

class Buffer;

namespace net
{

class Socket: noncopyable {
public:
    explicit
    Socket(int sockfd)
        : m_sockfd(sockfd)
    {}

    Socket(Socket&& sock)
        :m_sockfd(sock.m_sockfd)
    { sock.m_sockfd = -1; }
    
    Socket& operator=(Socket&& rhs){
        close();
        m_sockfd = rhs.m_sockfd;
        rhs.m_sockfd = -1;
        return *this;
    }

    ~Socket() {
        close();
    }

    int getFd() const {
        return m_sockfd;
    }

    int bind(const InetAddress& addr) const ;
    int listen(int nlisten) const ;
    int accept(InetAddress& peerAddr) const ;
    int connect(const InetAddress& addr) const ;

    ssize_t read(Buffer& buf) const ;
    ssize_t write(Buffer& buf) const ;
    ssize_t write(const char* msg) const;
    ssize_t write(const char* msg, std::size_t sz) const ;
    ssize_t write(const std::string& msg) const ;

    void shutdownWrite() const ;

    void setTcpNoDelay(bool on) const ;
    void setKeepAlive(bool on) const ;
    int getSocketError() const ;

    void close() ;

    InetAddress getPeerAddr() const ;
    InetAddress getLocalAddr() const ;
    int setReuse(bool reuse) const ;

    static
    int createSocket();

    static
    int write(int sockfd, const char* msg, std::size_t sz);

    static
    int read(int sockfd, char* buf, std::size_t sz);

    static
    void close(int sockfd);
private:
    int m_sockfd;
};

} // namespace net

} // namespace toym


#endif // __TOYM__NET__SOCKET_H__